Author

Ben Sunshine

4.1 Load R Packages

Code
library(reticulate)
library(tidyverse)
library(mapsapi)
library(mapboxapi)
library(magick)
Sys.which("python")
                                                   python 
"/Users/bensunshine/.virtualenvs/r-reticulate/bin/python" 

4.2 Download Aerial City Images

Code
key <- Sys.getenv("mapbox_key")
Code
map <- static_mapbox(
  access_token = key,
  style_url = "mapbox://styles/mapbox/satellite-v9",
  width = 300,
  height = 200, 
  image = T, latitude = 37.792004, longitude = -122.428079, zoom = 12
)

magick::image_write(map, "images/san_francisco_scale_zoom_12.png")
Code
points_of_interest <- tibble::tibble(
  longitude = c(-112.065945, -111.853948, 
                -111.852956, -112.023371),
  
  latitude = c(40.794275, 40.791516, 
               40.502308, 40.502308)
  )

prepped_pois <- prep_overlay_markers(
  data = points_of_interest,
  marker_type = "pin-l",
  label = 1:4,
  color = "#fff", 
)

map <- static_mapbox(
  access_token = key,
  style_url = "mapbox://styles/mapbox/satellite-v9",
  width = 800,
  height = 1200, 
  image = T, 
  latitude = 40.7,
  longitude = -111.876183, zoom = 12
)

magick::image_write(map, "images/salt_lake_city_zoom_12.png")
Code
map <- static_mapbox(
  access_token = key,
  style_url = "mapbox://styles/mapbox/satellite-v9",
  width = 1200,
  height = 800, 
  image = T, 
  latitude = 42.336322,
  longitude = -83.048705, zoom = 12
)

magick::image_write(map, "images/detroit_zoom_12.png")

San Francisco Cityscape

Salt Lake City Cityscape

Detroit Cityscape
Figure 4.1: Aerial Cityscape Images

4.3 Load Python Libraries

Code

import matplotlib.pyplot as plt
import pandas as pd

# jupyter only inline output command
#%matplotlib inline

from skimage.io import imread, imshow
from skimage.transform import resize
from skimage.feature import hog
from skimage import data, exposure


import matplotlib.pyplot as plt
from skimage import io
from skimage import color
from skimage.transform import resize
import math
from skimage.feature import hog
import numpy as np

4.4 Collect HOG Features for Aerial Cityscapes

Code
# List for storing images
img_list = []

# SF aerial
img_list.append(color.rgb2gray(io.imread("images/san_francisco_scale_zoom_12.png")))

# Salt Lake City Aerial
img_list.append(color.rgb2gray(io.imread("images/salt_lake_city_zoom_12.png")))

# Detroit Aerial
img_list.append(color.rgb2gray(io.imread("images/detroit_zoom_12.png")))


#img = color.rgb2gray(io.imread("images/grass_image2.jpg"))

# img = color.rgb2gray(io.imread("images/b_test_image_copy.jpg"))
#img = color.rgb2gray(io.imread("images/long_grass_sample.jpeg"))
#img = color.rgb2gray(io.imread("images/diagnol_lines.jpg"))

#img = color.rgb2gray(io.imread("images/san_francisco_scale_zoom_12.png"))

#img = color.rgb2gray(io.imread("images/diagnol_lines_flipped.jpg"))
#img = color.rgb2gray(io.imread("images/long_grass_sample_cropped.jpg"))

# aerial rotated image
#img = color.rgb2gray(io.imread("images/living_lab_aerial/aerial_grass_living_lab_rotated.jpg"))

# zoomed internet photo
#img = color.rgb2gray(io.imread("images/dead_grass_zoom.jpeg"))


# zoomed in 11
#img = color.rgb2gray(io.imread("images/living_lab_aerial/LL_zoomed_in_11.jpg"))

# zoomed in 12
#img = color.rgb2gray(io.imread("images/living_lab_aerial/LL_zoomed_in_12.jpg"))

# zoomed in 16
#img = color.rgb2gray(io.imread("images/living_lab_aerial/LL_zoomed_in_16_side.jpg"))



# real one
#img = color.rgb2gray(io.imread("images/living_labs_real_grass_image.jpg"))

# List to store magnitudes for each image
mag_list = []

# List to store angles for each image
theta_list = []


for x in range(len(img_list)):
    # Get image of interest
    img = img_list[x]
    
    rescaled_file_path = f"images/plots/aerial_cities/{x}.jpg"
    
    # Determine aspect Ratio
    aspect_ratio = img.shape[0] / img.shape[1]
    print("Aspect Ratio:", aspect_ratio)
    
    # Hard-Code height to 200 pixels
    height = 200
    
    # Calculate witdth to maintain same aspect ratio
    width = int(height / aspect_ratio)
    print("Resized Width:", width)
    
    # Resize the image
    resized_img = resize(img, (height, width))
    
    # Replace the original image with the resized image
    img_list[x] = resized_img
    
    if (x == 1):
      plot_width = 8
      plot_height = 15
    else:
      plot_width = 15
      plot_height = 9
    
    # plt.figure(figsize=(plot_width, plot_height))
    # plt.imshow(resized_img, cmap="gray")
    # plt.axis("on")
    # plt.tight_layout()
    # plt.savefig(rescaled_file_path, dpi=300)
    #plt.show()

    
    # list for storing all magnitudes for image[x]
    mag = []
    
    # list for storing all angles for image[x]
    theta = []
    
    for i in range(height):
        magnitudeArray = []
        angleArray = []
        
        for j in range(width):
            if j - 1 < 0 or j + 1 >= width:
                if j - 1 < 0:
                    Gx = img[i][j + 1] - 0
                elif j + 1 >= width:
                    Gx = 0 - img[i][j - 1]
            else:
                Gx = img[i][j + 1] - img[i][j - 1]
                
            if i - 1 < 0 or i + 1 >= height:
                if i - 1 < 0:
                    Gy = 0 - img[i + 1][j]
                elif i + 1 >= height:
                    Gy = img[i - 1][j] - 0
            else:
                Gy = img[i + 1][j] - img[i - 1][j]
                
            magnitude = math.sqrt(pow(Gx, 2) + pow(Gy, 2))
            magnitudeArray.append(round(magnitude, 9))
            
            if Gx == 0:
                angle = math.degrees(0.0)
            else:
                angle = math.degrees(math.atan(Gy / Gx))
                if angle < 0:
                    angle += 180
                    
            angleArray.append(round(angle, 9))
            
        mag.append(magnitudeArray)
        theta.append(angleArray)
    
    # add list of magnitudes to list[x]
    mag_list.append(mag)
    
    # add list of angles to angle list[x]
    theta_list.append(theta)
Aspect Ratio: 0.6666666666666666
Resized Width: 300
Aspect Ratio: 1.5
Resized Width: 133
Aspect Ratio: 0.6666666666666666
Resized Width: 300

San Francisco, CA

Salt Lake City, UT

Detroit, MI
Figure 4.2: Aerial Cityscape Images Rescaled and Converted to Greyscale

4.5 Build Data Frames for Each Aerial Cityscape

Code
mag_sf = np.array(mag_list[0])
theta_sf = np.array(theta_list[0])


mag_salt_lake = np.array(mag_list[1])
theta_salt_lake = np.array(theta_list[1])


mag_detroit = np.array(mag_list[2])
theta_detroit = np.array(theta_list[2])

4.6 Plot Magnitudes as Image for each Aerial Cityscape

Code

# plt.figure(figsize=(15, 8))
# #plt.title('San Francisco, CA Gradient Magnitudes')
# plt.imshow(mag_list[0], cmap="gray")
# plt.axis("on")
# #plt.show()
# plt.tight_layout()
# plt.savefig("images/plots/aerial_cities/sf_mag.png", dpi=300)
Code

#plt.figure(figsize=(8, 15))
#plt.title('Salt Lake City, UT Gradient Magnitudes')
# plt.imshow(mag_list[1], cmap="gray")
# plt.axis("on")
# #plt.show()
# plt.tight_layout()
# plt.savefig("images/plots/aerial_cities/salt_lake_mag.png", dpi=300)
Code

# plt.figure(figsize=(15, 8))
# #plt.title('Detroit, MI Gradient Magnitudes')
# plt.imshow(mag_list[2], cmap="gray")
# plt.axis("on")
# #plt.show()
# plt.tight_layout()
# plt.savefig("images/plots/aerial_cities/detroit_mag.png", dpi=300)

San Francisco, CA

Salt Lake City, UT

Detroit, MI
Figure 4.3: Aerial Cityscape Magnitudes

4.7 Create Data Frame for Each Image

Code
# Diagonal DF
sf_hog_df <- data.frame(mag = as.vector(py$mag_sf),
                              theta = as.vector((py$theta_sf))) %>%
  mutate(radian = theta*(pi/180))

# San Francisco DF
salt_lake_hog_df <- data.frame(mag = as.vector(py$mag_salt_lake),
                              theta = as.vector((py$theta_salt_lake))) %>%
  mutate(radian = theta*(pi/180))

# Internet Grass DF
detroit_hog_df <- data.frame(mag = as.vector(py$mag_detroit),
                              theta = as.vector((py$theta_detroit))) %>%
  mutate(radian = theta*(pi/180))


# List of all Data frames
standard_df_list = list(sf_hog_df,
                        salt_lake_hog_df, 
                        detroit_hog_df)

4.8 Create Histograms of Gradient Magnitudes and Angles for Aerial Cityscapes

Code
sf_histogram_mag_plot <-
  ggplot(standard_df_list[[1]], 
         aes(x = mag)) +
  geom_histogram(colour = "black", fill = "lightblue") +
  scale_x_continuous() + 
  labs(x = "Gradient Magnitude", 
       y = "Count", 
       title = "San Francisco Cityscape Image Histogram of Gradient Magnitudes"
       ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

#sf_histogram_mag_plot

sf_mag_filter <- 0.4

ggsave("images/plots/aerial_cities/sf_histogram_mag_plot.jpg", sf_histogram_mag_plot, width = 6, height = 4, dpi = 300)



sf_histogram_theta_plot <-
  ggplot(standard_df_list[[1]], 
         aes(x = theta)) +
  geom_histogram(colour = "black", fill = "lightblue") +
  scale_x_continuous() + 
  labs(x = "Gradient Angle", 
       y = "Count", 
       title = "San Francisco Cityscape Image Histogram of Gradient Angles"
       ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

#sf_histogram_theta_plot

ggsave("images/plots/aerial_cities/sf_histogram_theta_plot.jpg", sf_histogram_theta_plot, width = 6, height = 4, dpi = 300)
Code
salt_lake_histogram_mag_plot <-
  ggplot(standard_df_list[[2]], 
         aes(x = mag)) +
  geom_histogram(colour = "black", fill = "lightblue") +
  scale_x_continuous() + 
  labs(x = "Gradient Magnitude", 
       y = "Count", 
       title = "Salt Lake City Image Histogram of Gradient Magnitudes"
       ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

#salt_lake_histogram_mag_plot

salt_lake_mag_filter <- 0.4

ggsave("images/plots/aerial_cities/salt_lake_histogram_mag_plot.jpg", salt_lake_histogram_mag_plot, width = 6, height = 4, dpi = 300)



salt_lake_histogram_theta_plot <-
  ggplot(standard_df_list[[2]], 
         aes(x = theta)) +
  geom_histogram(colour = "black", fill = "lightblue") +
  scale_x_continuous() + 
  labs(x = "Gradient Angle", 
       y = "Count", 
       title = "Salt Lake City Image Histogram of Gradient Angles"
       ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

#salt_lake_histogram_theta_plot

ggsave("images/plots/aerial_cities/salt_lake_histogram_theta_plot.jpg", salt_lake_histogram_theta_plot, width = 6, height = 4, dpi = 300)
Code
detroit_histogram_mag_plot <-
  ggplot(standard_df_list[[3]], 
         aes(x = mag)) +
  geom_histogram(colour = "black", fill = "lightblue") +
  scale_x_continuous() + 
  labs(x = "Gradient Magnitude", 
       y = "Count", 
       title = "Detroit Image Histogram of Gradient Magnitudes"
       ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

#detroit_histogram_mag_plot

detroit_mag_filter <- 0.2

ggsave("images/plots/aerial_cities/detroit_histogram_mag_plot.jpg", detroit_histogram_mag_plot, width = 6, height = 4, dpi = 300)



detroit_histogram_theta_plot <-
  ggplot(standard_df_list[[3]], 
         aes(x = theta)) +
  geom_histogram(colour = "black", fill = "lightblue") +
  scale_x_continuous() + 
  labs(x = "Gradient Angle", 
       y = "Count", 
       title = "Detroit, MI Image Histogram of Gradient Angles"
       ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

#detroit_histogram_theta_plot

ggsave("images/plots/aerial_cities/detroit_histogram_theta_plot.jpg", detroit_histogram_theta_plot, width = 6, height = 4, dpi = 300)

Figure 4.4: Aerial Cityscape Magnitudes and Angles

4.9 Build New Distributed Histogram Data Frames

Code
# Define the number of bins
num_bins <- 9

# function to calculate the contributions to neighboring bins
calculate_bin_contributions <- function(angle, magnitude, num_bins) {
  bin_width <- 180 / num_bins
  contributions <- numeric(num_bins)
  
  # get the central bin
  central_bin <- floor(angle / bin_width) %% num_bins
  next_bin <- (central_bin + 1) %% num_bins
  
  # get contributions to neighboring bins
  weight <- (1 - abs((angle %% bin_width) / bin_width)) * magnitude
  
  contributions[central_bin + 1] <- weight
  contributions[next_bin + 1] <- magnitude - weight
  
  return(list(contributions[1],
         contributions[2],
         contributions[3],
         contributions[4],
         contributions[5],
         contributions[6],
         contributions[7],
         contributions[8],
         contributions[9])
         )
}

filtered_aerial_standard_df_list <-list(sf_hog_df %>%
                                   filter(mag >= sf_mag_filter),
                                 salt_lake_hog_df %>%
                                   filter(mag >= salt_lake_mag_filter), 
                                 detroit_hog_df %>%
                                   filter(mag >= detroit_mag_filter))
aerial_contribution_df_list <- list()

 
for (i in 1:length(filtered_aerial_standard_df_list)){
  
  aerial_contribution_hog_df <- 
    filtered_aerial_standard_df_list[[i]] %>%
    rowwise() %>%
    mutate(`0` = calculate_bin_contributions(theta, mag, 9)[[1]],
           `20` = calculate_bin_contributions(theta, mag, 9)[[2]],
           `40` = calculate_bin_contributions(theta, mag, 9)[[3]],
           `60` = calculate_bin_contributions(theta, mag, 9)[[4]],
           `80` = calculate_bin_contributions(theta, mag, 9)[[5]],
           `100` = calculate_bin_contributions(theta, mag, 9)[[6]],
           `120` = calculate_bin_contributions(theta, mag, 9)[[7]],
           `140` = calculate_bin_contributions(theta, mag, 9)[[8]],
           `160` = calculate_bin_contributions(theta, mag, 9)[[9]],
           )
  
  aerial_split_histo_df <- 
    aerial_contribution_hog_df %>%
    pivot_longer(names_to = "bin", 
                 values_to = "contribution", 
                 cols = 4:ncol(aerial_contribution_hog_df)) %>%
    mutate(bin = as.numeric(bin)) %>%
    group_by(bin) %>%
    summarise(contribution_sum = sum(contribution))
  
  
  aerial_contribution_df_list[[i]] <- aerial_split_histo_df

}

4.10 Generate Polar Plots for Standard Historgrams

Code
sf_plot <-
  ggplot(filtered_aerial_standard_df_list[[1]], 
         aes(x = theta)) +
  geom_histogram(colour = "black", 
                 fill = "lightblue", 
                 breaks = seq(0, 360, length.out = 17.5),
                 bins = 9) +
  coord_polar(
    theta = "x", 
    start = 0, 
    direction = 1) +
  scale_x_continuous(limits = c(0,360),
    breaks = c(0, 45, 90, 135, 180, 225, 270, 315), 
    labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW")
  )+
  labs(title = "Polar Plot of San Francisco, CA Image\nUsing Standard HOG Technique") +
  theme_minimal() +
  labs(x = "") +
  theme(axis.title.y = element_blank(),
        plot.title = element_text(hjust = 0.5))

ggsave("images/plots/aerial_cities/sf_standard_polar_plot.jpg", sf_plot, width = 6, height = 4, dpi = 300)
Code
salt_lake_plot <-
  ggplot(filtered_aerial_standard_df_list[[2]], 
         aes(x = theta)) +
  geom_histogram(colour = "black", 
                 fill = "lightblue", 
                 breaks = seq(0, 360, length.out = 17.5),
                 bins = 9) +
  coord_polar(
    theta = "x", 
    start = 0, 
    direction = 1) +
  scale_x_continuous(limits = c(0,360),
    breaks = c(0, 45, 90, 135, 180, 225, 270, 315), 
    labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW")
  )+
  labs(title = "Polar Plot of Salt Lake City, UT Image\nUsing Standard HOG Technique") +
  theme_minimal() +
  labs(x = "") +
  theme(axis.title.y = element_blank(),
        plot.title = element_text(hjust = 0.5))

ggsave("images/plots/aerial_cities/salt_lake_standard_polar_plot.jpg", salt_lake_plot, width = 6, height = 4, dpi = 300)
Code
detroit_plot <-
  ggplot(filtered_aerial_standard_df_list[[3]], 
         aes(x = theta)) +
  geom_histogram(colour = "black", 
                 fill = "lightblue", 
                 breaks = seq(0, 360, length.out = 17.5),
                 bins = 9) +
  coord_polar(
    theta = "x", 
    start = 0, 
    direction = 1) +
  scale_x_continuous(limits = c(0,360),
    breaks = c(0, 45, 90, 135, 180, 225, 270, 315), 
    labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW")
  )+
  labs(title = "Polar Plot of Detroit, MI Image\nUsing Standard HOG Technique") +
  theme_minimal() +
  labs(x = "") +
  theme(axis.title.y = element_blank(),
        plot.title = element_text(hjust = 0.5))

ggsave("images/plots/aerial_cities/detroit_standard_polar_plot.jpg", detroit_plot, width = 6, height = 4, dpi = 300)
Code
all_standard_city_plots <- ggpubr::ggarrange(sf_plot, 
                                             salt_lake_plot, 
                                             detroit_plot)

ggsave("images/plots/aerial_cities/all_standard_polar_plots.jpg", 
       all_standard_city_plots, 
       width = 7, 
       height = 7)

San Francisco, CA

Salt Lake City, UT

Detroit, MI
Figure 4.5: Aerial Cityscape Standard Polar Plots

4.11 Generate Polar Plots for Distributed Historgrams

Code
sf_split_plot <-
  ggplot(aerial_contribution_df_list[[1]], 
         aes(x = bin, y = contribution_sum)) +
  geom_histogram(stat = "identity",
                 colour = "black", 
                 fill = "lightblue", 
                 breaks = seq(0, 360, length.out = 17.5),
                 bins = 9) +
  coord_polar(
    theta = "x", 
    start = 0, 
    direction = 1) +
  scale_x_continuous(limits = c(0,360),
    breaks = c(0, 45, 90, 135, 180, 225, 270, 315), 
    labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW")
  )+
  labs(title = "Polar Plot of San Francisco, CA Image\nUsing Distributed HOG Technique") +
  theme_minimal() +
  labs(x = "") +
  theme(axis.title.y = element_blank(),
        plot.title = element_text(hjust = 0.5))

ggsave("images/plots/aerial_cities/sf_contribution_polar_plot.jpg", sf_split_plot, width = 6, height = 4, dpi = 300)
Code
salt_lake_split_plot <-
  ggplot(aerial_contribution_df_list[[2]], 
         aes(x = bin, y = contribution_sum)) +
  geom_histogram(stat = "identity",
                 colour = "black", 
                 fill = "lightblue", 
                 breaks = seq(0, 360, length.out = 17.5),
                 bins = 9) +
  coord_polar(
    theta = "x", 
    start = 0, 
    direction = 1) +
  scale_x_continuous(limits = c(0,360),
    breaks = c(0, 45, 90, 135, 180, 225, 270, 315), 
    labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW")
  )+
  labs(title = "Polar Plot of Salt Lake City, UT Image\nUsing Distributed HOG Technique") +
  theme_minimal() +
  labs(x = "") +
  theme(axis.title.y = element_blank(),
        plot.title = element_text(hjust = 0.5))

ggsave("images/plots/aerial_cities/salt_lake_contribution_polar_plot.jpg", salt_lake_split_plot, width = 6, height = 4, dpi = 300)
Code
detroit_split_plot <-
  ggplot(aerial_contribution_df_list[[3]], 
         aes(x = bin, y = contribution_sum)) +
  geom_histogram(stat = "identity",
                 colour = "black", 
                 fill = "lightblue", 
                 breaks = seq(0, 360, length.out = 17.5),
                 bins = 9) +
  coord_polar(
    theta = "x", 
    start = 0, 
    direction = 1) +
  scale_x_continuous(limits = c(0,360),
    breaks = c(0, 45, 90, 135, 180, 225, 270, 315), 
    labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW")
  )+
  labs(title = "Polar Plot of Detroit, MI Image\nUsing Distributed HOG Technique") +
  theme_minimal() +
  labs(x = "") +
  theme(axis.title.y = element_blank(),
        plot.title = element_text(hjust = 0.5))

ggsave("images/plots/aerial_cities/detroit_contribution_polar_plot.jpg", detroit_split_plot, width = 6, height = 4, dpi = 300)
Code
all_aerial_contribution_plots <- ggpubr::ggarrange(sf_split_plot, 
                                                   salt_lake_split_plot, 
                                                   detroit_split_plot)

ggsave("images/plots/aerial_cities/all_aerial_contribution_plots.jpg", 
       all_aerial_contribution_plots, 
       width = 7, 
       height = 7)

San Francisco, CA

Salt Lake City, UT

Detroit, MI
Figure 4.6: Aerial Cityscape Distributed Method Polar Plots

4.12 Collect HOG Features for Grass Images

Code
# List for storing images
img_list = []

# Internet Grass Image
img_list.append(color.rgb2gray(io.imread("images/grass_image2.jpg")))

# Living Labs Rotated Aerial Grass
img_list.append(color.rgb2gray(io.imread("images/living_lab_aerial/aerial_grass_living_lab_rotated.jpg")))

# Living Labs Grass Close-up
img_list.append(color.rgb2gray(io.imread("images/living_lab_aerial/LL_zoomed_in_12.jpg")))


#img = color.rgb2gray(io.imread("images/grass_image2.jpg"))

# img = color.rgb2gray(io.imread("images/b_test_image_copy.jpg"))
#img = color.rgb2gray(io.imread("images/long_grass_sample.jpeg"))
#img = color.rgb2gray(io.imread("images/diagnol_lines.jpg"))

#img = color.rgb2gray(io.imread("images/san_francisco_scale_zoom_12.png"))

#img = color.rgb2gray(io.imread("images/diagnol_lines_flipped.jpg"))
#img = color.rgb2gray(io.imread("images/long_grass_sample_cropped.jpg"))

# aerial rotated image
#img = color.rgb2gray(io.imread("images/living_lab_aerial/aerial_grass_living_lab_rotated.jpg"))

# zoomed internet photo
#img = color.rgb2gray(io.imread("images/dead_grass_zoom.jpeg"))


# zoomed in 11
#img = color.rgb2gray(io.imread("images/living_lab_aerial/LL_zoomed_in_11.jpg"))

# zoomed in 12
#img = color.rgb2gray(io.imread("images/living_lab_aerial/LL_zoomed_in_12.jpg"))

# zoomed in 16
#img = color.rgb2gray(io.imread("images/living_lab_aerial/LL_zoomed_in_16_side.jpg"))



# real one
#img = color.rgb2gray(io.imread("images/living_labs_real_grass_image.jpg"))

# List to store magnitudes for each image
mag_list = []

# List to store angles for each image
theta_list = []


for x in range(len(img_list)):
    # Get image of interest
    img = img_list[x]
    
    rescaled_file_path = f"images/plots/grass/{x}.jpg"
    
    # Determine aspect Ratio
    aspect_ratio = img.shape[0] / img.shape[1]
    print("Aspect Ratio:", aspect_ratio)
    
    # Hard-Code height to 200 pixels
    height = 200
    
    # Calculate witdth to maintain same aspect ratio
    width = int(height / aspect_ratio)
    print("Resized Width:", width)
    
    # Resize the image
    resized_img = resize(img, (height, width))
    
    # Replace the original image with the resized image
    img_list[x] = resized_img
    
    # plt.figure(figsize=(plot_width, plot_height))
    # plt.imshow(resized_img, cmap="gray")
    # plt.axis("on")
    # plt.tight_layout()
    # plt.savefig(rescaled_file_path, dpi=300)
    # plt.show()

    
    # list for storing all magnitudes for image[x]
    mag = []
    
    # list for storing all angles for image[x]
    theta = []
    
    for i in range(height):
        magnitudeArray = []
        angleArray = []
        
        for j in range(width):
            if j - 1 < 0 or j + 1 >= width:
                if j - 1 < 0:
                    Gx = img[i][j + 1] - 0
                elif j + 1 >= width:
                    Gx = 0 - img[i][j - 1]
            else:
                Gx = img[i][j + 1] - img[i][j - 1]
                
            if i - 1 < 0 or i + 1 >= height:
                if i - 1 < 0:
                    Gy = 0 - img[i + 1][j]
                elif i + 1 >= height:
                    Gy = img[i - 1][j] - 0
            else:
                Gy = img[i + 1][j] - img[i - 1][j]
                
            magnitude = math.sqrt(pow(Gx, 2) + pow(Gy, 2))
            magnitudeArray.append(round(magnitude, 9))
            
            if Gx == 0:
                angle = math.degrees(0.0)
            else:
                angle = math.degrees(math.atan(Gy / Gx))
                if angle < 0:
                    angle += 180
                    
            angleArray.append(round(angle, 9))
            
        mag.append(magnitudeArray)
        theta.append(angleArray)
    
    # add list of magnitudes to list[x]
    mag_list.append(mag)
    
    # add list of angles to angle list[x]
    theta_list.append(theta)
Aspect Ratio: 0.662751677852349
Resized Width: 301
Aspect Ratio: 0.4904214559386973
Resized Width: 407
Aspect Ratio: 0.5625
Resized Width: 355

Internet Grass Image

Living Labs Aerial Image

Living Labs Close-Up Image
Figure 4.7: Grass Images Rescaled and Converted to Greyscale

4.13 Build Data Frames for Each Grass Image

Code
mag_internet_grass = np.array(mag_list[0])
theta_internet_grass = np.array(theta_list[0])


mag_aerial_living_lab = np.array(mag_list[1])
theta_aerial_living_lab = np.array(theta_list[1])


mag_close_up_living_lab = np.array(mag_list[2])
theta_close_up_living_lab = np.array(theta_list[2])

4.14 Plot Magnitudes as Image for each Aerial Cityscape

Code

# plt.figure(figsize=(15, 8))
# #plt.title('San Francisco, CA Gradient Magnitudes')
# plt.imshow(mag_list[0], cmap="gray")
# plt.axis("on")
# #plt.show()
# plt.tight_layout()
# plt.savefig("images/plots/grass/internet_grass_mag.png", dpi=300)
Code
# plt.figure(figsize=(15, 8))
# #plt.title('Salt Lake City, UT Gradient Magnitudes')
# plt.imshow(mag_list[1], cmap="gray")
# plt.axis("on")
# #plt.show()
# plt.tight_layout()
# plt.savefig("images/plots/grass/aerial_living_lab_grass_mag.png", dpi=300)
Code
# plt.figure(figsize=(15, 8))
# #plt.title('Detroit, MI Gradient Magnitudes')
# plt.imshow(mag_list[2], cmap="gray")
# plt.axis("on")
# #plt.show()
# plt.tight_layout()
# plt.savefig("images/plots/grass/close_up_living_lab_grass_mag.png", dpi=300)

Internet Grass

Aerial Living Labs

Close-Up Living Labs
Figure 4.8: Grass Image Magnitudes

4.15 Create Data Frame for Each Image

Code
# Diagonal DF
internet_grass_hog_df <- data.frame(mag = as.vector(py$mag_internet_grass),
                              theta = as.vector((py$theta_internet_grass))) %>%
  mutate(radian = theta*(pi/180))

# San Francisco DF
aerial_living_lab_hog_df <- data.frame(mag = as.vector(py$mag_aerial_living_lab),
                              theta = as.vector((py$theta_aerial_living_lab))) %>%
  mutate(radian = theta*(pi/180))

# Internet Grass DF
close_up_living_lab_hog_df <- data.frame(mag = as.vector(py$mag_close_up_living_lab),
                              theta = as.vector((py$theta_close_up_living_lab))) %>%
  mutate(radian = theta*(pi/180))


# List of all Data frames
grass_standard_df_list = list(internet_grass_hog_df,
                        aerial_living_lab_hog_df, 
                        close_up_living_lab_hog_df)

4.16 Create Histograms of Gradient Magnitudes and Angles for Aerial Cityscapes

Code
internet_grass_histogram_mag_plot <-
  ggplot(grass_standard_df_list[[1]], 
         aes(x = mag)) +
  geom_histogram(colour = "black", fill = "lightblue") +
  scale_x_continuous() + 
  labs(x = "Gradient Magnitude", 
       y = "Count", 
       title = "Internet Grass Image Histogram of Gradient Magnitudes"
       ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

#internet_grass_histogram_mag_plot

internet_grass_mag_filter <- 0.3

ggsave("images/plots/grass/internet_grass_histogram_mag_plot.jpg", internet_grass_histogram_mag_plot, width = 6, height = 4, dpi = 300)



internet_grass_histogram_theta_plot <-
  ggplot(grass_standard_df_list[[1]], 
         aes(x = theta)) +
  geom_histogram(colour = "black", fill = "lightblue") +
  scale_x_continuous() + 
  labs(x = "Gradient Angle", 
       y = "Count", 
       title = "Internet Grass Image Histogram of Gradient Angles"
       ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

#internet_grass_histogram_theta_plot

ggsave("images/plots/grass/internet_grass_histogram_theta_plot.jpg", internet_grass_histogram_theta_plot, width = 6, height = 4, dpi = 300)
Code
aerial_living_lab_histogram_mag_plot <-
  ggplot(grass_standard_df_list[[2]], 
         aes(x = mag)) +
  geom_histogram(colour = "black", fill = "lightblue") +
  scale_x_continuous() + 
  labs(x = "Gradient Magnitude", 
       y = "Count", 
       title = "Aerial Living Labs Image Histogram of Gradient Magnitudes"
       ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

#aerial_living_lab_histogram_mag_plot

aerial_living_lab_mag_filter <- 0.2

ggsave("images/plots/grass/aerial_living_lab_histogram_mag_plot.jpg", aerial_living_lab_histogram_mag_plot, width = 6, height = 4, dpi = 300)



aerial_living_lab_histogram_theta_plot <-
  ggplot(grass_standard_df_list[[2]], 
         aes(x = theta)) +
  geom_histogram(colour = "black", fill = "lightblue") +
  scale_x_continuous() + 
  labs(x = "Gradient Angle", 
       y = "Count", 
       title = "Aerial Living Labs Image Histogram of Gradient Angles"
       ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

#aerial_living_lab_histogram_theta_plot

ggsave("images/plots/grass/aerial_living_lab_histogram_theta_plot.jpg", aerial_living_lab_histogram_theta_plot, width = 6, height = 4, dpi = 300)
Code
close_up_living_lab_histogram_mag_plot <-
  ggplot(grass_standard_df_list[[3]], 
         aes(x = mag)) +
  geom_histogram(colour = "black", fill = "lightblue") +
  scale_x_continuous() + 
  labs(x = "Gradient Magnitude", 
       y = "Count", 
       title = "Close-Up Living Labs Histogram of Gradient Magnitudes"
       ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

#close_up_living_lab_histogram_mag_plot

close_up_living_lab_mag_filter <- 0.2

ggsave("images/plots/grass/close_up_living_lab_histogram_mag_plot.jpg", close_up_living_lab_histogram_mag_plot, width = 6, height = 4, dpi = 300)



close_up_living_lab_histogram_theta_plot <-
  ggplot(grass_standard_df_list[[3]], 
         aes(x = theta)) +
  geom_histogram(colour = "black", fill = "lightblue") +
  scale_x_continuous() + 
  labs(x = "Gradient Angle", 
       y = "Count", 
       title = "Close-Up Living Labs Image Histogram of Gradient Angles"
       ) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

#close_up_living_lab_histogram_theta_plot

ggsave("images/plots/grass/close_up_living_lab_histogram_theta_plot.jpg", close_up_living_lab_histogram_theta_plot, width = 6, height = 4, dpi = 300)

Figure 4.9: Grass Image Magnitudes and Angles

4.17 Build New Distributed Histogram Data Frames for Grass Images

Code
# Define the number of bins
num_bins <- 9

filtered_grass_standard_df_list <-list(internet_grass_hog_df %>%
                                          filter(mag >= internet_grass_mag_filter),
                                        aerial_living_lab_hog_df %>%
                                          filter(mag >= aerial_living_lab_mag_filter), 
                                        close_up_living_lab_hog_df %>%
                                          filter(mag >= close_up_living_lab_mag_filter))
grass_contribution_df_list <- list()

 
for (i in 1:length(filtered_grass_standard_df_list)){
  
  grass_contribution_hog_df <- 
    filtered_grass_standard_df_list[[i]] %>%
    rowwise() %>%
    mutate(`0` = calculate_bin_contributions(theta, mag, 9)[[1]],
           `20` = calculate_bin_contributions(theta, mag, 9)[[2]],
           `40` = calculate_bin_contributions(theta, mag, 9)[[3]],
           `60` = calculate_bin_contributions(theta, mag, 9)[[4]],
           `80` = calculate_bin_contributions(theta, mag, 9)[[5]],
           `100` = calculate_bin_contributions(theta, mag, 9)[[6]],
           `120` = calculate_bin_contributions(theta, mag, 9)[[7]],
           `140` = calculate_bin_contributions(theta, mag, 9)[[8]],
           `160` = calculate_bin_contributions(theta, mag, 9)[[9]],
           )
  
  grass_split_histo_df <- 
    grass_contribution_hog_df %>%
    pivot_longer(names_to = "bin", 
                 values_to = "contribution", 
                 cols = 4:ncol(grass_contribution_hog_df)) %>%
    mutate(bin = as.numeric(bin)) %>%
    group_by(bin) %>%
    summarise(contribution_sum = sum(contribution))
  
  
  grass_contribution_df_list[[i]] <- grass_split_histo_df

}

4.18 Generate Grass Image Polar Plots for Standard Historgrams

Code
internet_grass_plot <-
  ggplot(filtered_grass_standard_df_list[[1]], 
         aes(x = theta)) +
  geom_histogram(colour = "black", 
                 fill = "lightblue", 
                 breaks = seq(0, 360, length.out = 17.5),
                 bins = 9) +
  coord_polar(
    theta = "x", 
    start = 0, 
    direction = 1) +
  scale_x_continuous(limits = c(0,360),
    breaks = c(0, 45, 90, 135, 180, 225, 270, 315), 
    labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW")
  )+
  labs(title = "Polar Plot of Internet Grass Image\nUsing Standard HOG Technique") +
  theme_minimal() +
  labs(x = "") +
  theme(axis.title.y = element_blank(),
        plot.title = element_text(hjust = 0.5))

ggsave("images/plots/grass/internet_grass_standard_polar_plot.jpg", internet_grass_plot, width = 6, height = 4, dpi = 300)
Code
aerial_living_lab_plot <-
  ggplot(filtered_grass_standard_df_list[[2]], 
         aes(x = theta)) +
  geom_histogram(colour = "black", 
                 fill = "lightblue", 
                 breaks = seq(0, 360, length.out = 17.5),
                 bins = 9) +
  coord_polar(
    theta = "x", 
    start = 0, 
    direction = 1) +
  scale_x_continuous(limits = c(0,360),
    breaks = c(0, 45, 90, 135, 180, 225, 270, 315), 
    labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW")
  )+
  labs(title = "Polar Plot of Aerial Living Labs Image\nUsing Standard HOG Technique") +
  theme_minimal() +
  labs(x = "") +
  theme(axis.title.y = element_blank(),
        plot.title = element_text(hjust = 0.5))

ggsave("images/plots/grass/aerial_living_lab_standard_polar_plot.jpg", aerial_living_lab_plot, width = 6, height = 4, dpi = 300)
Code
close_up_living_lab_plot <-
  ggplot(filtered_grass_standard_df_list[[3]], 
         aes(x = theta)) +
  geom_histogram(colour = "black", 
                 fill = "lightblue", 
                 breaks = seq(0, 360, length.out = 17.5),
                 bins = 9) +
  coord_polar(
    theta = "x", 
    start = 0, 
    direction = 1) +
  scale_x_continuous(limits = c(0,360),
    breaks = c(0, 45, 90, 135, 180, 225, 270, 315), 
    labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW")
  )+
  labs(title = "Polar Plot of Close-Up Living Lab Image\nUsing Standard HOG Technique") +
  theme_minimal() +
  labs(x = "") +
  theme(axis.title.y = element_blank(),
        plot.title = element_text(hjust = 0.5))

ggsave("images/plots/grass/close_up_living_lab_standard_polar_plot.jpg", close_up_living_lab_plot, width = 6, height = 4, dpi = 300)
Code
all_standard_grass_plots <- ggpubr::ggarrange(internet_grass_plot, 
                                             aerial_living_lab_plot, 
                                             close_up_living_lab_plot)

ggsave("images/plots/grass/all_grass_standard_polar_plots.jpg", 
       all_standard_grass_plots, 
       width = 7, 
       height = 7)

Internet Grass Image

Aerial Living Labs Image

Close-Up Living Labs Image
Figure 4.10: Aerial Cityscape Standard Polar Plots

4.19 Generate Grass Image Polar Plots for Distributed Historgrams

Code
internet_grass_split_plot <-
  ggplot(grass_contribution_df_list[[1]], 
         aes(x = bin, y = contribution_sum)) +
  geom_histogram(stat = "identity",
                 colour = "black", 
                 fill = "lightblue", 
                 breaks = seq(0, 360, length.out = 17.5),
                 bins = 9) +
  coord_polar(
    theta = "x", 
    start = 0, 
    direction = 1) +
  scale_x_continuous(limits = c(0,360),
    breaks = c(0, 45, 90, 135, 180, 225, 270, 315), 
    labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW")
  )+
  labs(title = "Polar Plot of Internet Grass Image\nUsing Distributed HOG Technique") +
  theme_minimal() +
  labs(x = "") +
  theme(axis.title.y = element_blank(),
        plot.title = element_text(hjust = 0.5))

ggsave("images/plots/grass/internet_grass_contribution_polar_plot.jpg", internet_grass_split_plot, width = 6, height = 4, dpi = 300)
Code
aerial_living_lab_split_plot <-
  ggplot(grass_contribution_df_list[[2]], 
         aes(x = bin, y = contribution_sum)) +
  geom_histogram(stat = "identity",
                 colour = "black", 
                 fill = "lightblue", 
                 breaks = seq(0, 360, length.out = 17.5),
                 bins = 9) +
  coord_polar(
    theta = "x", 
    start = 0, 
    direction = 1) +
  scale_x_continuous(limits = c(0,360),
    breaks = c(0, 45, 90, 135, 180, 225, 270, 315), 
    labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW")
  )+
  labs(title = "Polar Plot of Aerial Living Lab Image\nUsing Distributed HOG Technique") +
  theme_minimal() +
  labs(x = "") +
  theme(axis.title.y = element_blank(),
        plot.title = element_text(hjust = 0.5))

ggsave("images/plots/grass/aerial_living_lab_contribution_polar_plot.jpg", aerial_living_lab_split_plot, width = 6, height = 4, dpi = 300)
Code
close_up_living_lab_split_plot <-
  ggplot(grass_contribution_df_list[[3]], 
         aes(x = bin, y = contribution_sum)) +
  geom_histogram(stat = "identity",
                 colour = "black", 
                 fill = "lightblue", 
                 breaks = seq(0, 360, length.out = 17.5),
                 bins = 9) +
  coord_polar(
    theta = "x", 
    start = 0, 
    direction = 1) +
  scale_x_continuous(limits = c(0,360),
    breaks = c(0, 45, 90, 135, 180, 225, 270, 315), 
    labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW")
  )+
  labs(title = "Polar Plot of Close-Up Living Lab Image\nUsing Distributed HOG Technique") +
  theme_minimal() +
  labs(x = "") +
  theme(axis.title.y = element_blank(),
        plot.title = element_text(hjust = 0.5))

ggsave("images/plots/grass/close_up_living_lab_contribution_polar_plot.jpg", close_up_living_lab_split_plot, width = 6, height = 4, dpi = 300)
Code
all_grass_contribution_plots <- ggpubr::ggarrange(internet_grass_split_plot, 
                                                  aerial_living_lab_split_plot, 
                                                  close_up_living_lab_split_plot)

ggsave("images/plots/grass/all_grass_contribution_plots.jpg", 
       all_grass_contribution_plots, 
       width = 7, 
       height = 7)

Internet Grass Image

Aerial Living Labs Image

Close-Up Living Labs Grass Image
Figure 4.11: Distributed Method Polar Plots for Grass Images